import * as Cesium from 'cesium'
import ConeGlowBottomCircleMaterialProperty from './ConeGlowBottomCircleMaterialProperty'
import WallGradientsMaterialProperty from './ConeMaterial'
import SimpleLabel from '@/cesiumTools/Bubble/htmlMarker.js'
import { getCirclePoints } from './core'
import getCesiumHeat from './cesiumHeatMap'
import { destination } from 'turf'
import { head } from 'lodash'

// 光锥
export const coneWithLight = (viewer, options, isCache) => {
  const position = Cesium.defaultValue(options.position, Cesium.Cartesian3.ZERO)
  const height = Cesium.defaultValue(options.height, 700)
  const bottomRadius = Cesium.defaultValue(options.bottomRadius, 100)
  const color = Cesium.defaultValue(options.color, Cesium.Color.AQUA)
  const modelMatrix = Cesium.Matrix4.multiplyByTranslation(
    Cesium.Transforms.eastNorthUpToFixedFrame(position),
    new Cesium.Cartesian3(0.0, 0.0, height * 0.5),
    new Cesium.Matrix4()
  )

  const cylinderGeometry = new Cesium.CylinderGeometry({
    length: height,
    topRadius: 0.0,
    bottomRadius: bottomRadius * 0.7,
    vertexFormat:
      Cesium.MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat,
  })

  const cone = new Cesium.GeometryInstance({
    geometry: cylinderGeometry,
    modelMatrix: modelMatrix,
  })

  return viewer.scene.primitives.add(
    new Cesium.Primitive({
      //其他情况为显示
      //发展历程默认为显示
      show: isCache,
      geometryInstances: [cone],
      appearance: new Cesium.MaterialAppearance({
        material: new Cesium.Material({
          fabric: {
            type: 'VtxfShader1',
            uniforms: {
              color: color,
            },
            source: /*glsl*/ `
                            uniform vec4 color;   
                            czm_material czm_getMaterial(czm_materialInput materialInput)
                            {
                                czm_material material = czm_getDefaultMaterial(materialInput);
                                vec2 st = materialInput.st;
                                float time=fract(czm_frameNumber/10.0);
                                float isAlpha=step(0.5,time);
                                float dis = distance(st, vec2(0.5)); 
                                material.diffuse =1.9 * color.rgb;
                                if(isAlpha>=1.0){
                                    material.alpha = color.a * dis *2.0;
                                }else{
                                    material.alpha = color.a * dis *1.5;
                                }

                                return material;
                            }
                        `,
          },
          translucent: false,
        }),
        faceForward: false, // 当绘制的三角面片法向不能朝向视点时，自动翻转法向，从而避免法向计算后发黑等问题
        closed: true, // 是否为封闭体，实际上执行的是是否进行背面裁剪
      }),
    })
  )
}

// 站点底部圆环
export const bottomCircle = (viewer, options, isCache) => {
  const position = Cesium.defaultValue(options.position, Cesium.Cartesian3.ZERO)
  const color = Cesium.defaultValue(options.color, Cesium.Color.AQUA)
  const bottomRadius = Cesium.defaultValue(options.bottomRadius, 100)
  return viewer.entities.add({
    show: isCache,
    position: position,
    ellipse: {
      semiMinorAxis: bottomRadius * 2,
      semiMajorAxis: bottomRadius * 2,
      height: 0.0,
      material: new ConeGlowBottomCircleMaterialProperty(color),
    },
  })
}

// 渲染站点  传入颜色十六进制字符串，名称，位置{lng,lat,height}
const stations = []
export const renderStation = (viewer, options, isCache) => {
  const position = Cesium.defaultValue(options.positions, {
    lng: 0,
    lat: 0,
  })
  const positionCar3 = Cesium.Cartesian3.fromDegrees(position.lng, position.lat)
  const conePrimitve = coneWithLight(
    viewer,
    {
      position: positionCar3,
      //站点高度
      height: 300,
      bottomRadius: 100,
      color: Cesium.Color.fromCssColorString(options.color),
    },
    isCache
  )

  const bottomCircleEntity = bottomCircle(
    viewer,
    {
      position: positionCar3,
      bottomRadius: 100,
      color: Cesium.Color.fromCssColorString(options.color),
    },
    isCache
  )
  const target = {
    conePrimitve,
    bottomCircleEntity,
    name: options.name,
  }
  if (isCache) {
    stations.push(target)
  }
  return target
}

// 删除单个站点，直接删除，而不是隐藏
export const removeStationByName = (viewer, name) => {
  const target = stations.find((item) => item.name === name)
  if (target) {
    const { conePrimitve, bottomCircleEntity } = target
    viewer.scene.primitives.remove(conePrimitve)
    viewer.entities.remove(bottomCircleEntity)
    stations.splice(stations.indexOf(target), 1)
  }
}

// 删除所有站点
export const removeAllStations = (viewer) => {
  stations.forEach((item) => {
    const { conePrimitve, bottomCircleEntity } = item
    viewer.scene.primitives.remove(conePrimitve)
    viewer.entities.remove(bottomCircleEntity)
  })
  stations.length = 0
}

// 通过名称Array控制站点显示隐藏
export const hideStationByName = (names, isShow) => {
  const targets = stations.filter((item) => names.indexOf(item.name) > -1)
  if (targets.length) {
    targets.forEach((target) => {
      const { conePrimitve, bottomCircleEntity } = target
      conePrimitve.show = isShow
      bottomCircleEntity.show = isShow
    })
  }
}

// 创建地铁线路 positions:[{lng,lat,height}]
// color:十六进制颜色字符串
// name:线路名称
const lines = []
export const renderLines = (viewer, options, isCache) => {
  const positions = Cesium.defaultValue(options.positions, [
    {
      lng: 0,
      lat: 0,
    },
  ])
  const color = Cesium.defaultValue(options.color, Cesium.Color.AQUA)
  const name = Cesium.defaultValue(options.name, 'line')
  //将经纬度数组转换为cesium坐标数组
  const positionRes = Cesium.Cartesian3.fromDegreesArray(positions)
  //创建线路
  const lineEnt = viewer.entities.add({
    name,
    //是否显示，当渲染发展历程中的数据时默认不显示，只有点击播放按钮才显示
    //其他情况为显示
    show: isCache,
    polyline: {
      positions: positionRes,
      width: 20,
      //使用cesium默认的泛光线
      material: new Cesium.PolylineGlowMaterialProperty({
        color: color,
        glowPower: 0.12,
      }),
    },
  })
  //存入缓存数组中
  if (isCache) {
    lines.push(lineEnt)
  }
  return lineEnt
}

// 删除地铁线路，不是隐藏
export const removeAllLines = (viewer) => {
  lines.forEach((line) => {
    line && viewer.entities.remove(line)
  })
}

// 通过名称控制线路显示隐藏
export const hideLineByName = (names, isShow) => {
  lines.forEach((line) => {
    if (names.indexOf(line.name) > -1) {
      line.show = isShow
    }
  })
}

// 清除全部
export const removeAll = (viewer) => {
  removeAllLines(viewer)
  removeAllStations(viewer)
}

// 渲染站点标牌，后期还要添加点击查询功能
let billboards = []
export const renderStationBill = (viewer, options) => {
  const position = Cesium.defaultValue(options.positions, {
    lng: 0,
    lat: 0,
  })
  const height = Cesium.defaultValue(options.height, 400)
  const name = Cesium.defaultValue(options.name, '站点')
  const show = Cesium.defaultValue(options.show, true)
  const color = Cesium.defaultValue(options.color, '#ff0000')
  const attr = Cesium.defaultValue(options.attr, {})
  // console.log(attr, name)
  const billControler = new SimpleLabel(viewer, {
    position: Cesium.Cartesian3.fromDegrees(position.lng, position.lat, height),
    isShow: show,
    color: color,
    scaleByDistance: new Cesium.NearFarScalar(1000, 1, 20000, 0.4),
    attr: attr,
    label: name,
  })
  const billboard = billControler.addLabel()
  const target = {
    billControler,
    billboard,
  }
  if (options.show) {
    billboards.push(target)
  }
  return target
}

// 清除所有站点标牌
export const removeAllBillboards = () => {
  billboards.forEach((item) => {
    const { billControler } = item
    billControler.removeMarker()
  })
}

// 根据名称Array控制站点标牌显示与隐藏
export const changeDisplayBillBoard = (names, isShow) => {
  const filterBills = billboards.filter(
    (item) => names.indexOf(item.billControler.label) > -1
  )
  filterBills.forEach(async (item) => {
    const { billboard, billControler } = item
    billControler.isDisplay = isShow
    //billboard 是一个promise对象
    const bill = await billboard
    if (isShow) {
      bill.style.display = 'block'
    } else {
      bill.style.display = 'none'
    }
  })
}
/**
 * 按名称删除站点标牌
 * @param {String} name 站点名称
 */
export const removeBillboardByName = async (name) => {
  const target = billboards.find(item => item.billControler.label === name)
  if (target) {
      const { billControler,billboard} = target   
      billboard.then((billboard) => {
          billControler.removeMarker()
          billboards.splice(billboards.indexOf(target), 1)
      })  
  }
}
/**
 * 判断重复站点数据,删除并返回红色，用以更新站点数据
 * @param {*} name 
 */
const checkDuplicateStation = (viewer,name) => {
  const target = stations.find(item => item.name === name)
  if (target) {
      // console.log(name)
      removeStationByName(viewer,name)
      removeBillboardByName(name)
      return true
  }
  else{
      return false
  }
}


/**
 *
 * @param {Cesium.Viewer} viewer
 * @param {Array<Object} dataSource 存储线路数据对象的数组
 * @param {Boolean} isCache 是否要将由线路数据构成的实体存入缓存数组中，
 * 默认为ture,当处理发展历程时不需要存入缓存数组中,此时为false
 */
export const renderAll = (viewer, dataSource) => {
  // console.log(dataSource);
  //当渲染发展历程中的数据时需要返回一个实体的对象
  // 渲染道路
  if (dataSource.length) {
    dataSource.forEach((item) => {
      const { paths, name, color, stationsList } = item
      const position = []
      paths.forEach((path) => {
        position.push(path.lng, path.lat)
      })
      // console.log(position);
      renderLines(
        viewer,
        {
          positions: position,
          color: new Cesium.Color.fromCssColorString(color),
          name,
        },
        true
      )
      // 渲染站点
      stationsList.forEach((station) => {
        const { position, name } = station
        const isDuplicate = checkDuplicateStation(viewer,name)
        renderStation(
          viewer,
          {
            positions: position,
            name,
            color:isDuplicate?'#ff0000':color
          },
          true
        )
        // 渲染站点标牌
        renderStationBill(viewer, {
          positions: position,
          color: isDuplicate?'#ff0000':color,
          name,
          show: true,
          attr: {
            name: name,
          },
        })
      })
    })
  }
}

/*=================重点活动===================*/
/**
 * 经纬度坐标转换函数，转换为笛卡尔坐标
 * @param {Array} positions 经纬度坐标数组
 * @returns {Array} 笛卡尔坐标数组
 */
const positionsToCartesian = (positions, height) => {
  const baseHeight = Cesium.defaultValue(height, 0)
  const cartesianPositions = []
  positions.forEach((position) => {
    let cartesianPosition
    if (position.lng && position.lat) {
      cartesianPosition = Cesium.Cartesian3.fromDegrees(
        position.lng,
        position.lat
      )
    } else {
      cartesianPosition = Cesium.Cartesian3.fromDegrees(
        position[0],
        position[1],
        baseHeight
      )
    }
    cartesianPositions.push(cartesianPosition)
  })
  return cartesianPositions
}

/**
 * 首页渲染所有线数据并记录
 * @param {Cesium.Viewer} viewer 视图对象
 * @param {Array} lines 所有线数据
 */
let allLines = []
export const renderAllLines = (viewer, lines) => {
  lines.forEach((line) => {
    const positions = Cesium.defaultValue(line.paths, [{ lng: 0, lat: 0 }])
    let color = Cesium.defaultValue(line.color, Cesium.Color.AQUA)
    const name = Cesium.defaultValue(line.name, '未命名')
    //转换坐标
    const position = positionsToCartesian(positions)
    //判断颜色是否为字符串
    if (typeof color === 'string') {
      color = Cesium.Color.fromCssColorString(color)
    }
    const lineEntity = viewer.entities.add({
      name: name,
      polyline: {
        positions: position,
        width: 5,
        //发光线材质
        material: new Cesium.PolylineGlowMaterialProperty({
          color: color,
          glowPower: 0.2,
          // taperPower: 0.5,
        }),
      },
    })
    allLines.push(lineEntity)
  })
  // console.log(allLines)
}

/**
 * 飞行到目标线
 */
export const flyToTargetLine = (viewer, lineName) => {
  const targetLine = lines.find((line) => line.name === lineName)
  if (targetLine) {
    viewer.flyTo(targetLine)
  }
}
/**
 * 闪烁高亮
 * @param {String} lineName 目标线名称
 */
//闪烁计时器
let timer = null
//当前高亮线
let lastClickedLine = null
export const flashHighlight = (lineName) => {
  const targetLine = lines.find((line) => line.name === lineName)
  /* 不存在目标线 */
  if (!targetLine) {
    return
  }
  /* 防止重复点击 */
  if (timer && lastClickedLine && lineName === lastClickedLine.name) {
    return
  }
  /* 如果有定时器，且点击线与定时器记录的线不一致，则清除定时器，恢复原状 */
  if (timer && lineName !== lastClickedLine.name) {
    clearInterval(timer)
    /* 恢复亮度 */
    lastClickedLine.polyline.material.glowPower = 0.12
    lastClickedLine.polyline.width = 20
  }
  /* 记录当前计时器对应高亮线 */
  lastClickedLine = targetLine
  /* 闪烁 */
  const glowPower = targetLine.polyline.material.glowPower
  const width = targetLine.polyline.width
  let count = 0
  let maxCount = 6
  /* 闪烁计时器,根据count%2的布尔值来控制是否加亮达成闪烁 */
  timer = setInterval(() => {
    if (count >= maxCount) {
      clearInterval(timer)
      timer = null
    } else {
      let flag = count % 2 === 0
      // console.log(flag)
      targetLine.polyline.material.glowPower = flag ? glowPower * 4 : glowPower
      targetLine.polyline.width = flag ? width * 1.2 : width
      count++
    }
  }, 500)
}

/**
 * 添加重点保护活动圆柱
 */
//圆柱集合
let ActivityCones = []
const addActivityCone = (viewer, options) => {
  let color = Cesium.defaultValue(options.color, Cesium.Color.AQUA)
  if (typeof color === 'string') {
    color = Cesium.Color.fromCssColorString(color)
  }
  /* 圆柱大小高度半径 */
  const wallHeight = Cesium.defaultValue(options.wallHeight, 1500)
  const baseHeight = Cesium.defaultValue(options.baseHeight, 0)
  const radius = Cesium.defaultValue(options.radius, 200)
  const name = Cesium.defaultValue(options.name, '未命名')
  // console.log(color, wallHeight, baseHeight, radius, name)
  /* 圆柱中心 */
  const center = Cesium.defaultValue(options.center, {
    lng: 0,
    lat: 0,
    height: 0,
  })
  // console.log(center)
  //圆柱边缘
  const pointsArr = getCirclePoints([center.lng, center.lat], radius)
  // console.log(pointsArr)
  const positions = positionsToCartesian(pointsArr, baseHeight)
  // console.log(positions)
  //圆柱顶点集合
  let topPositions = []
  let bottomPositions = []
  /* 根据边缘点计算顶点 */
  positions.forEach((position) => {
    topPositions.push(baseHeight + wallHeight)
    bottomPositions.push(baseHeight)
  })
  const cone = viewer.entities.add({
    name: name,
    center: new Cesium.Cartesian3.fromDegrees(
      center.lng,
      center.lat,
      baseHeight
    ),
    wall: {
      positions: positions,
      minimumHeights: bottomPositions,
      maximumHeights: topPositions,
      material: new WallGradientsMaterialProperty(color),
    },
  })
  ActivityCones.push(cone)
}
/**
 * 添加所有重点保护圆柱
 * @param {*} viewer
 * @param {Array<Object>} LineStation 站点数据
 * @param {String} color 圆柱颜色
 */
export const addAllCones = (viewer, LineStation, color) => {
  LineStation.forEach((item) => {
    const { position, id } = item
    addActivityCone(viewer, {
      center: position,
      name: id,
      color: color,
    })
  })
  console.log(ActivityCones)
}
/**
 * 移除所有重点保护圆柱
 * @param {*} viewer
 */
export const removeAllCones = (viewer) => {
  ActivityCones.forEach((cone) => {
    cone && viewer.entities.remove(cone)
  })
  ActivityCones.length = 0
}

/**
 * 飞行至目标圆柱
 */
export const flyToTargetCone = (viewer, SelectedCone) => {
  const targetCone = ActivityCones.find((cone) => cone.name === SelectedCone.id)
  if (targetCone) {
    viewer.flyTo(targetCone, {
      offset: new Cesium.HeadingPitchRange(
        Cesium.Math.toRadians(10),
        -Cesium.Math.toRadians(45),
        2000
      ),
    })
  }
}

/**
 *
 * @param {Array<String>} lineNames 地铁线路的名字的数组
 * @param {Array<String>} stationNames 站点的名字的数组
 * @param {Boolean} isShow ture=>显示 fasle=>隐藏
 */
export const displayByName = (lineNames, stationNames, isShow) => {
  hideLineByName(lineNames, isShow)
  hideStationByName(stationNames, isShow)
  changeDisplayBillBoard(stationNames, isShow)
}

/**
 *
 * @param {Cesium.Viewer} viewer
 * @param {Object} dataEnts 发展历程组件消失时消除的实体
 * @returns
 */
export const removeByCacheData = (viewer, dataEnts) => {
  const keys = Object.keys(dataEnts)
  if (!keys.length) return
  //   lineEnts: [lineEnt],
  //    stationEnts: stationEnts,
  //    billboards: billboards,
  const lineEnts = dataEnts.lineEnts
  const stationEnts = dataEnts.stationEnts
  const billboards = dataEnts.billboards
  //移除线路实体
  lineEnts.forEach((ent) => {
    viewer.entities.remove(ent)
  })
  //移除光锥和底部圆
  // conePrimitve,
  // bottomCircleEntity,
  // name: options.name,
  stationEnts.forEach((primitive) => {
    const { conePrimitve, bottomCircleEntity } = primitive
    viewer.scene.primitives.remove(conePrimitve)
    viewer.entities.remove(bottomCircleEntity)
  })
  //移除站点牌
  billboards.forEach((billboard) => {
    const { billControler } = billboard
    billControler.removeMarker()
  })
}

/**
 *
 * @param {Cesium.Viewer} viewer
 * @param {Object} item 每一条线路的对象
 */
export const flyToDefaultView = (viewer, item) => {
  const position = item.stationsList[0].position
  //114.23470683746325,30.652633577333606
  viewer.camera.flyTo({
    destination: Cesium.Cartesian3.fromDegrees(
      position.lng,
      position.lat,
      20000
    )
  })
}



/* =================站点管理============ */
// 渲染热力图,传入站点坐标，站点信息，渲染热力图
// dataSource Array<{
//  lng,lat,value
//}>
export const renderHeat = (viewer, dataSource) => {
  const CesiumHeat = getCesiumHeat(Cesium);
  let heat = new CesiumHeat(
      viewer,
      {
          autoMaxMin: true,
          // data list, each has x, y, and value | 数据数组，每个包含 x,y,value字段
          data: dataSource,
      },
      // bbox for heatmap | 只在范围内显示热力图拉近会清晰些，默认整个地球但拉近后巨模糊
      [114.03, 30.2, 114.45, 30.9]
  );

  const destroyHeat = () => {
      heat.destory();
  };
  // 将清除方法暴露出去
  return destroyHeat;
};

// 通过名称找到对应的站点，站牌
export const findyBillboardByName = (name) => {
  let billboardsData = billboards
  let stationsData = stations
  // 根据传入的站牌名称在站牌信息中找到对应的站牌
  const targetBillboard = billboardsData.find((item) => item.billControler.label === name);
  // 根据传入的站点名称在所有站点信息中找到对应的站点
  const stationEnt = stationsData.find((item) => item.name === name);
  return {
      billboard: targetBillboard,
      station: stationEnt,
  }
}

// 聚焦到站点并展示查询信息
export const focusOnStation = (viewer, name) => {
  const target = findyBillboardByName(name);
  const { billboard: { billControler }, station } = target

  if (station && billControler) {
      const { bottomCircleEntity } = station
      viewer.flyTo(bottomCircleEntity, {
          // 偏移量, HeadingPitchRange: 航向角度，俯仰角度，距离
          offset: new Cesium.HeadingPitchRange(Cesium.Math.toRadians(40), Cesium.Math.toRadians(-40), 5000)
      });
      // 调用billControler的showQueryPopup方法
      billControler.showQueryPopup()
  }
}
/**
 * 规划模式下的跳转逻辑
 * @param {*} viewer 
 * @param {*} name 
 */
export const flyToStation = (viewer, name,data) => {
  const {billboards,stationEnts} = data
  // console.log(billboards,stationEnts,name)
  const targetLabel = billboards.find((item) => item.billControler.label === name||item.billControler.label === name+'(换乘)');
  const target = stationEnts.find((item) => item.name === name||item.name === name+'(换乘)');
  if (targetLabel && target) {
      const { bottomCircleEntity } = target
      const { billControler } = targetLabel
      viewer.flyTo(bottomCircleEntity, {
          // 偏移量, HeadingPitchRange: 航向角度，俯仰角度，距离
          offset: new Cesium.HeadingPitchRange(Cesium.Math.toRadians(40), Cesium.Math.toRadians(-40), 5000)
      });
      // 调用billControler的showQueryPopup方法
      billControler.showQueryPopup()
  }
}

export const flyToEntireView = (viewer,target) => {
  // console.log(target)
  viewer.flyTo(target)
};
